home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Cappuccino / Source / CappuccinoUtils.cpp < prev    next >
Encoding:
Text File  |  1995-12-11  |  31.4 KB  |  1,145 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CappuccinoUtils.cpp
  3.  
  4.     Contains:    Cappuccino utility functions & classes
  5.  
  6.     Written by:    Steve Smith and Troy Gaul
  7.  
  8.     Copyright:    © 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. // -- Compiler/Preprocessor Switches --
  12.  
  13. #ifndef _COMPILERDEFS_
  14. #include "CompDefs.h"
  15. #endif
  16.  
  17. // -- OpenDoc Utilities --
  18.  
  19. #ifndef _EXCEPT_
  20. // Exceptions define several important macros (ie. CHECKENV)
  21. // which are used in the SOM method dispatch glue. If Except.h
  22. // is not included early enough, exceptions may not be thrown
  23. // correctly when returning from a SOM method with the "ev" parameter set.
  24. #include <Except.h>
  25. #endif
  26.  
  27. // --- Cappuccino Includes ---
  28.  
  29. #ifndef _CAPPUCCINOUTILS_
  30. #include "CappuccinoUtils.h"
  31. #endif
  32.  
  33. #ifndef _CAPPUCCINODEF_
  34. #include "CappuccinoDef.h"
  35. #endif
  36.  
  37. // --- OpenDoc Includes ---
  38.  
  39. #ifndef SOM_ODArbitrator_xh
  40. #include <Arbitrat.xh>
  41. #endif
  42.  
  43. #ifndef SOM_ODFacet_xh
  44. #include <Facet.xh>
  45. #endif
  46.  
  47. #ifndef SOM_ODFrame_xh
  48. #include <Frame.xh>
  49. #endif
  50.  
  51. #ifndef SOM_ODDocument_xh
  52. #include <Document.xh>
  53. #endif
  54.  
  55. #ifndef SOM_ODDraft_xh
  56. #include <Draft.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODNameSpaceManager_xh
  60. #include <NmSpcMg.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODContainer_xh
  64. #include <ODCtr.xh>
  65. #endif
  66.  
  67. #ifndef SOM_ODSession_xh
  68. #include <ODSessn.xh>
  69. #endif
  70.  
  71. #ifndef _ODTYPES_
  72. #include <ODTypes.h>
  73. #endif
  74.  
  75. #ifndef SOM_Module_OpenDoc_StdProps_defined
  76. #include <StdProps.xh>
  77. #endif
  78.  
  79. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  80. #include <StdTypes.xh>
  81. #endif
  82.  
  83. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  84. #include <StdDefs.xh>
  85. #endif
  86.  
  87. #ifndef SOM_ODStorageUnit_xh
  88. #include <StorageU.xh>
  89. #endif
  90.  
  91. #ifndef SOM_ODStorageUnitView_xh
  92. #include <SUView.xh>
  93. #endif
  94.  
  95. #ifndef SOM_ODValueNameSpace_xh
  96. #include <ValueNS.xh>
  97. #endif
  98.  
  99. #ifndef SOM_ODWindowState_xh
  100. #include <WinStat.xh>
  101. #endif
  102.  
  103. // -- OpenDoc Utilities --
  104.  
  105. #ifndef _BNDNSUTL_
  106. #include <BndNSUtl.h>
  107. #endif
  108.  
  109. #ifndef _DLOGUTIL_
  110. #include <DlogUtil.h>
  111. #endif
  112.  
  113. #ifndef _DOCUTILS_
  114. #include <DocUtils.h>
  115. #endif
  116.  
  117. #ifndef _ISOSTR_
  118. #include <ISOStr.h>
  119. #endif
  120.  
  121. #ifndef _ODDEBUG_
  122. #include <ODDebug.h>
  123. #endif
  124.  
  125. #ifndef _ODUTILS_
  126. #include <ODUtils.h>
  127. #endif
  128.  
  129. #ifndef _STDTYPIO_
  130. #include <StdTypIO.h>
  131. #endif
  132.  
  133. #ifndef _STORUTIL_    
  134. #include <StorUtil.h>
  135. #endif
  136.  
  137. #ifndef _TEMPOBJ_
  138. #include <TempObj.h>
  139. #endif
  140.  
  141. #ifndef _TEMPITER_
  142. #include <TempIter.h>
  143. #endif
  144.  
  145. #ifndef _USERSRCM_
  146. #include <UseRsrcM.h>
  147. #endif
  148.  
  149. // --- Macintosh Includes ---
  150.  
  151. #ifndef __GESTALT__
  152. #include <Gestalt.h>
  153. #endif
  154.  
  155. #ifndef __GXMATH__
  156. #include <GXMath.h>
  157. #endif
  158.  
  159. #ifndef __RESOURCES__
  160. #include <Resources.h>
  161. #endif
  162.  
  163. #ifndef __SCRIPT__
  164. #include <Script.h>
  165. #endif
  166.  
  167. #ifndef __SPEECH__
  168. #include <Speech.h>
  169. #endif
  170.  
  171. #ifndef __TEXTUTILS__
  172. #include <TextUtils.h>
  173. #endif
  174.  
  175.  
  176. #pragma segment CappuccinoUtilities
  177.  
  178.  
  179. //==============================================================================
  180. // Utility Functions
  181. //==============================================================================
  182. #pragma mark • Utility Functions •
  183.  
  184. //------------------------------------------------------------------------------
  185. // GetPartName
  186. //------------------------------------------------------------------------------
  187.  
  188. ODIText* GetPartName(Environment* ev, ODPart* part, ODType category)
  189. {
  190.     ASSERT(part != kODNULL, kODErrIllegalNullPartInput);
  191.  
  192.     // Get the root part of the document.
  193.     ODDraft* draft = ODGetDraft(ev,part);
  194.     TempODPart rootPart = ODAcquireRootPartOfDraft(ev, draft);
  195.     
  196.     // Get the part name.
  197.     // If we can't get a valid name for the part, we generate one using
  198.     // the user visible category name of the part's category.
  199.     TempODIText partName = ODGetITextProp(ev, part->GetStorageUnit(ev), 
  200.                                          kODPropName, kODMacIText, kODNULL);
  201.     
  202.     // If the part is the root of the document, return the name of the file.
  203.     if ( ODObjectsAreEqual(ev, part, rootPart) )
  204.     {
  205.         ODContainer* container = draft->GetDocument(ev)->GetContainer(ev);
  206.         TempPlatformFile file = GetPlatformFileFromContainer(ev, container);
  207.  
  208.         TempODIText fileName = file->GetName();
  209.         
  210.         // Test the file name against the part name. If the two are equivalent
  211.         // (not equal), then use the part name.
  212.         if ( !NamesAreEquivalent(ev, fileName, partName) )
  213.         {
  214.             // If the names are different, return the file name.
  215.             // (This code transfers the ODIText object to the partName tempobj)
  216.             DisposeIText(partName.DontDelete());
  217.             partName = fileName.DontDelete();
  218.         }
  219.     }
  220.     else
  221.     {
  222.         if ( (partName == kODNULL) || (GetITextStringLength(partName) == 0) )
  223.         {
  224.             ODIText* categoryName;
  225.             ODNameSpaceManager* nsMgr = ODGetSession(ev,part)->GetNameSpaceManager(ev);
  226.             
  227.             // Get the category string from the category name space.
  228.             if ( GetUserCatFromCat(nsMgr, category, &categoryName) )
  229.             {
  230.                 // If we successfully retrieved the category user string, return it.
  231.                 // (This code transfers the ODIText object to the partName tempobj)
  232.                 DisposeIText(partName.DontDelete());
  233.                 partName = categoryName;
  234.             }
  235.             else
  236.             {
  237.     #if ODDebug
  238.                 // This should never happen. Check NMAP for errors.
  239.                 DebugStr("\pCategory NMAP bad, or Preferences corrupted.");
  240.     #else
  241.                 THROW(kODErrInvalidNSType);
  242.     #endif
  243.             }
  244.         }
  245.     }
  246.     
  247.     return partName.DontDelete();
  248. }
  249.  
  250. //------------------------------------------------------------------------------
  251. // NamesAreEquivalent
  252. //------------------------------------------------------------------------------
  253.  
  254. ODBoolean NamesAreEquivalent(Environment* ev, ODIText* fileName,
  255.                                         ODIText* partName)
  256. {
  257.     Str255 fileStr;
  258.     Str255 partStr;
  259.     
  260.     // If the strings are in different languages, we're done.
  261.     if ( (GetITextScriptCode(fileName) != GetITextScriptCode(partName)) ||
  262.             GetITextLangCode(fileName) != GetITextLangCode(partName) )
  263.         return kODFalse;
  264.     
  265.     GetITextPString(fileName, fileStr);
  266.     GetITextPString(partName, partStr);
  267.  
  268.     // If the string lengths are different, we're done.
  269.     if ( fileStr[0] != partStr[0] )
  270.         return kODFalse;
  271.  
  272.     // Return the Toolbox string equivalence test.
  273.     return EqualString(fileStr,partStr,kODTrue,kODTrue);
  274. }
  275.  
  276. //------------------------------------------------------------------------------
  277. // GetEditorScriptLanguage
  278. //------------------------------------------------------------------------------
  279.  
  280. void GetEditorScriptLanguage(Environment* ev, ODScriptCode* script,
  281.                                         ODLangCode* language)
  282. {
  283.     long region;
  284.     
  285.     ODSLong rfRef;
  286.     rfRef = BeginUsingLibraryResources();
  287.     {
  288.         Handle versHdl = Get1Resource('vers', 1);
  289.         
  290.         // Get the region code of the editor, otherwise use the
  291.         // region code the of the primary system script.
  292.         
  293.         if ( versHdl )
  294.         {
  295.             region = (long)(*(VersRecHndl)versHdl)->countryCode;
  296.             ReleaseResource(versHdl);
  297.         }
  298.         else
  299.         {
  300.             region = GetScriptManagerVariable(smRegionCode);
  301.         }
  302.         
  303.         // Spanish & Japanese are not actually supported by the editor.
  304.         // They are provided as examples of how to add recognition of
  305.         // additional regions (see Script.h for region codes).
  306.         
  307.         switch ((short)region) {
  308.             case verUS:
  309.                 *script = smRoman;
  310.                 *language = langEnglish;
  311.                 break;
  312.             case verSpain:
  313.                 *script = smRoman;
  314.                 *language = langSpanish;
  315.                 break;
  316.             case verJapan:
  317.                 *script = smJapanese;
  318.                 *language = langJapanese;
  319.                 break;
  320.             default:
  321.                 *script = smRoman;
  322.                 *language = langEnglish;
  323.         }                
  324.     }
  325.     EndUsingLibraryResources(rfRef);
  326. }
  327.  
  328. //------------------------------------------------------------------------------
  329. // FixedToIntRect
  330. //------------------------------------------------------------------------------
  331.  
  332. void FixedToIntRect(ODRect& fixedRect, Rect& intRect)
  333. {
  334.     intRect.top        = FixedToInt(fixedRect.top);
  335.     intRect.left    = FixedToInt(fixedRect.left);
  336.     intRect.bottom    = FixedToInt(fixedRect.bottom);
  337.     intRect.right    = FixedToInt(fixedRect.right);
  338. }
  339.  
  340. //------------------------------------------------------------------------------
  341. // IntToFixedRect
  342. //------------------------------------------------------------------------------
  343.  
  344. void IntToFixedRect(Rect& intRect, ODRect& fixedRect)
  345. {
  346.     fixedRect.left        = ff(intRect.left);
  347.     fixedRect.top        = ff(intRect.top);
  348.     fixedRect.right        = ff(intRect.right);
  349.     fixedRect.bottom    = ff(intRect.bottom);
  350. }
  351.  
  352. //------------------------------------------------------------------------------
  353. // LoadThumbnail
  354. //------------------------------------------------------------------------------
  355.  
  356. void LoadThumbnail(Environment* ev, Handle* thumbnail)
  357. {
  358.     if ( *thumbnail ) return;
  359.     
  360.     ODSLong rfRef;
  361.     rfRef = BeginUsingLibraryResources();
  362.     {
  363.         *thumbnail = (Handle) GetPicture(kThumbnailPicture);
  364.     }
  365.     EndUsingLibraryResources(rfRef);
  366. }
  367.  
  368. //------------------------------------------------------------------------------
  369. // TilePartWindow
  370. //------------------------------------------------------------------------------
  371.  
  372. Rect TilePartWindow(Environment* ev, Rect* facetBounds, Rect* partWindowBounds)
  373. {
  374.     const short    kWindowTilingConst    = 20;
  375.     const short kLeftToRight        = 0;
  376.     const short kRightToLeft        = -1;
  377.     
  378.     short direction;
  379.     
  380.     // Get the direction for the primary script system running on this machine.
  381.     // (Right-to-Left or Left-to-Right)
  382.     direction = GetSysDirection();
  383.     
  384.     // The child window should be tiled from the topLeft corner of the 
  385.     // active facet whose frame is being opened.
  386.     if ( direction == kLeftToRight )
  387.     {
  388.         // Position the window rect at the top/left corner of the facet.
  389.         OffsetRect(partWindowBounds, facetBounds->left, facetBounds->top);
  390.         // Now tile the window rect down and to the right.
  391.         OffsetRect(partWindowBounds, kWindowTilingConst, kWindowTilingConst);
  392.     }
  393.     // The child window should be tiled from the topRight corner of the 
  394.     // active facet whose frame is being opened.
  395.     else if ( direction == kRightToLeft )
  396.     {
  397.         // Position the window rect at the top/right corner of the facet.
  398.         OffsetRect(partWindowBounds, (partWindowBounds->right - facetBounds->right),
  399.                     facetBounds->top);
  400.         // Now tile the window rect down and to the left.
  401.         OffsetRect(partWindowBounds, -kWindowTilingConst, kWindowTilingConst);
  402.     }
  403.     
  404.     return *partWindowBounds;
  405. }
  406.  
  407. //------------------------------------------------------------------------------
  408. // CountFacets
  409. //------------------------------------------------------------------------------
  410.  
  411. ODUShort CountFacets(Environment* ev, ODFrame* frame)
  412. {
  413.     ODUShort facetCount = 0;
  414.     ODFacet* facet;
  415.     
  416.     TempODFrameFacetIterator ffiter(ev, frame);
  417.     facet = ffiter.First();
  418.     while ( ffiter.IsNotComplete() )
  419.     {
  420.         facetCount++;
  421.         facet = ffiter.Next();
  422.     }
  423.     
  424.     return facetCount;
  425. }
  426.  
  427. //------------------------------------------------------------------------------
  428. // HasFocusFromSet
  429. //------------------------------------------------------------------------------
  430.  
  431. ODBoolean HasAnyFocusInSet(Environment* ev, ODFrame* frame, ODFocusSet* set)
  432. {
  433.     ASSERT_NOT_NULL(frame);
  434.     ASSERT_NOT_NULL(set);
  435.  
  436.     ODBoolean hasFocus = kODFalse;
  437.     
  438.     TempODFocusSetIterator iter(ev, set);
  439.     for ( ODTypeToken focus = iter.First(); iter.IsNotComplete(); 
  440.           focus = iter.Next() )
  441.     {
  442.         TempODPart part = frame->AcquirePart(ev);
  443.         ODArbitrator* arbitrator = ODGetSession(ev, part)->GetArbitrator(ev);
  444.     
  445.         TempODFrame focusFrame = arbitrator->AcquireFocusOwner(ev, focus);
  446.         if ( ODObjectsAreEqual(ev, focusFrame, frame) )
  447.         {
  448.             hasFocus = kODTrue;
  449.             break;
  450.         }
  451.     }
  452.     
  453.     return hasFocus;
  454. }
  455.  
  456. //------------------------------------------------------------------------------
  457. // SetPreferredKind
  458. //------------------------------------------------------------------------------
  459.  
  460. void SetPreferredKind( Environment*        ev, 
  461.                        ODStorageUnit*    su,
  462.                        ODValueType        kind )
  463. {
  464.     TRY
  465.         if ( kind == kODNULL )
  466.             ODSURemoveProperty(ev, su, kODPropPreferredKind);
  467.         else
  468.             ODSetISOStrProp(ev, su, kODPropPreferredKind, kODISOStr, kind);
  469.     CATCH_ALL
  470.         // Remove the property and value if something went wrong.
  471.         ODSURemoveProperty(ev, su, kODPropPreferredKind);
  472.     ENDTRY
  473. }
  474.  
  475. //------------------------------------------------------------------------------
  476. // DuplicateISOStr
  477. //------------------------------------------------------------------------------
  478.  
  479. ODISOStr DuplicateISOStr( ODISOStr string )
  480. {
  481.     // Since ISO strings are just C strings, we call the following ODUtils
  482.     // routine:
  483.     return ODISOStrFromCStr(string);
  484. }
  485.  
  486. //------------------------------------------------------------------------------
  487. // HasSpeech
  488. //------------------------------------------------------------------------------
  489.  
  490. ODBoolean HasSpeech()
  491. {
  492.     ODBoolean hasSpeech = kODFalse;
  493.  
  494. #ifdef powerc
  495.     // There is not yet a CFM-68K shared library for the speech manager, so
  496.     // we must disable that menu item.
  497.     
  498.     long response;
  499.     OSErr error = Gestalt(gestaltSpeechAttr, &response);
  500.     
  501.     if ( error == noErr 
  502.         && (response & (1 << gestaltSpeechMgrPresent))
  503.         && (void*) SpeakString != (void*) kUnresolvedCFragSymbolAddress )
  504.     {
  505.         hasSpeech = kODTrue;
  506.     }
  507. #endif
  508.     
  509.     return hasSpeech;
  510. }
  511.  
  512. //------------------------------------------------------------------------------
  513. // FINF struct
  514. //------------------------------------------------------------------------------
  515.  
  516. struct FINF 
  517. {
  518.     short    font;
  519.     short    face;
  520.     short    size;
  521. };
  522.  
  523. //------------------------------------------------------------------------------
  524. // GetIndFINF
  525. // (must have focused resource fork before calling)
  526. //------------------------------------------------------------------------------
  527.  
  528. static FINF GetIndFINF(short id, short num)
  529. {
  530.     FINF finf;
  531.  
  532.     finf.font = systemFont;
  533.     finf.face = 0;
  534.     finf.size = 0;
  535.  
  536.     if (num > 0)
  537.     {
  538.         Handle fh = GetResource('finf', id);
  539.         if ( fh && num <= *(short *)(*fh) )
  540.             finf = ((FINF*) ((*fh) + 2)) [num - 1];
  541.     }
  542.     
  543.     return finf;
  544. }
  545.  
  546. //------------------------------------------------------------------------------
  547. // SetDialogDefaults
  548. //------------------------------------------------------------------------------
  549.  
  550. void SetDialogDefaults(DialogPtr dialog, ODUShort finfID, ODUShort index)
  551. {
  552.     FINF finf;
  553.  
  554.     SetDialogDefaultItem(dialog, ok);
  555.     SetDialogCancelItem(dialog, cancel);
  556.         
  557.     if ( finfID != 0 )
  558.     {    
  559.         SetPort(dialog);
  560.         
  561.         finf = GetIndFINF(finfID, index);
  562.         
  563.         TextFont(finf.font);
  564.         TextSize(finf.size);
  565.         TextFace(finf.face);
  566.         
  567.         DialogPeek dialogPeek = (DialogPeek) dialog;
  568.         (**(dialogPeek->textH)).txFont = finf.font;
  569.         (**(dialogPeek->textH)).txSize = finf.size;
  570.         (**(dialogPeek->textH)).txFace = finf.face;
  571.         
  572.         FontInfo finfo;
  573.         GetFontInfo(&finfo);
  574.         (**(dialogPeek->textH)).lineHeight = finfo.leading + finfo.ascent + finfo.descent;
  575.         (**(dialogPeek->textH)).fontAscent = finfo.ascent;
  576.         
  577.         TECalText(dialogPeek->textH);
  578.     }
  579. }
  580.  
  581. //------------------------------------------------------------------------------
  582. // IsNumericCharacter
  583. //------------------------------------------------------------------------------
  584.  
  585. static ODBoolean IsNumericCharacter( UInt32 charKeyCode )
  586. {
  587.     char charCode = charKeyCode & charCodeMask;
  588.     return (charCode >= '0' && charCode <= '9');
  589. }
  590.  
  591. //------------------------------------------------------------------------------
  592. // IsControlCharacter
  593. //------------------------------------------------------------------------------
  594.  
  595. static ODBoolean IsControlCharacter( UInt32 charKeyCode )
  596. {
  597.     const char kMaxControlChar = 0x1f;
  598.  
  599.     char charCode = charKeyCode & charCodeMask;
  600.     return (charCode <= kMaxControlChar);
  601. }
  602.  
  603. //------------------------------------------------------------------------------
  604. // IntegerDialogFilter
  605. //------------------------------------------------------------------------------
  606.  
  607. pascal ODBoolean IntegerDialogFilter( DialogPtr            dialog, 
  608.                                       EventRecord*        event,
  609.                                       short*            itemHit )
  610. {
  611.     ODBoolean result = kODFalse;
  612.  
  613.     if ( event->what == keyDown )    // just looking for keystrokes
  614.     {
  615.         if ( !IsNumericCharacter(event->message) && !IsControlCharacter(event->message) )
  616.         {
  617.             char charCode = event->message & charCodeMask;
  618.             ODBoolean disallow = kODFalse;
  619.             
  620.             switch ( charCode ) 
  621.             {
  622.                 case '.':
  623.                     // We need to allow command-., but disallow just '.':
  624.                     if ( (event->modifiers & cmdKey) != cmdKey ) 
  625.                         disallow = kODTrue;
  626.                     break;
  627.         
  628.                 default:
  629.                     // For all non-numeric keystrokes, beep at the user
  630.                     // and clear the event so the char is not typed.
  631.                     disallow = kODTrue;
  632.                     break;
  633.             }
  634.             
  635.             if ( disallow )
  636.             {
  637.                 // In order to disallow the entry, beep at the user
  638.                 // and clear the event so the char is not typed.
  639.                 SysBeep(1);
  640.                 event->what = nullEvent;
  641.             }
  642.         }
  643.     }
  644.     
  645.     if ( result == kODFalse )
  646.         result = ODDialogFilterProc(dialog, event, itemHit);
  647.     
  648.     return result;
  649. }
  650.  
  651. //==============================================================================
  652. // CTempDialogState helper class
  653. //
  654. //    This is a stack-based object that sets up state for a modal dialog in its
  655. //    constructor, and resets the state in the destructor. It deactivates the 
  656. //    front window, removes the "Redo" item from the Edit menu, and updates the 
  657. //    Mac scrap.
  658. //
  659. //    This is similar to the CWithDialogState class from the printing utility, 
  660. //    but this version also ensapsulates the usage of library resources so that 
  661. //    they will be available for the life of the dialog.  
  662. //==============================================================================
  663. #pragma mark • CTempDialogState •
  664.  
  665. //------------------------------------------------------------------------------
  666. // CTempDialogState Constructor
  667. //------------------------------------------------------------------------------
  668.  
  669. CTempDialogState::CTempDialogState( Environment *ev, ODSession *session )
  670. {
  671.     fEv            = ev;
  672.     fSession    = session;
  673.     fDialogPtr    = kODNULL;
  674.     fResRefNum    = -1;
  675.     
  676.     fResRefNum = BeginUsingLibraryResources();
  677.     TempODMenuBar menuBar = fSession->GetWindowState(ev)->AcquireCurrentMenuBar(ev);
  678.     fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
  679.     ODDialogBegin(ev, session, menuBar, kODNULL);
  680. }
  681.  
  682. //------------------------------------------------------------------------------
  683. // CTempDialogState Destructor
  684. //------------------------------------------------------------------------------
  685.  
  686. CTempDialogState::~CTempDialogState( )
  687. {
  688.     if (fDialogPtr)
  689.     {
  690.         DisposeDialog(fDialogPtr);
  691.         fDialogPtr = kODNULL;
  692.     }
  693.     
  694.     ODDialogEnd();
  695.     fSession->GetWindowState(fEv)->ActivateFrontWindows(fEv);
  696.     
  697.     ODSLong ref = fResRefNum;
  698.     if ( ref != -1 )             // Make sure it's done only once
  699.     {
  700.         fResRefNum = -1;
  701.         EndUsingLibraryResources(ref);
  702.     }
  703. }
  704.  
  705. //------------------------------------------------------------------------------
  706. // CTempDialogState::CreateDialog
  707. //------------------------------------------------------------------------------
  708. DialogPtr CTempDialogState::CreateDialog( ODSShort resID )
  709. {
  710.     WASSERT(fDialogPtr == kODNULL);
  711.     
  712.     fDialogPtr = ODGetNewDialog(fEv, resID, fSession);
  713.     THROW_IF_NULL(fDialogPtr);
  714.     
  715.     return fDialogPtr;
  716. }
  717.                                           
  718. //==============================================================================
  719. // CFrameProxy
  720. //==============================================================================
  721. #pragma mark • CFrameProxy •
  722.  
  723. //------------------------------------------------------------------------------
  724. // CFrameProxy::~CFrameProxy
  725. //------------------------------------------------------------------------------
  726.  
  727. CFrameProxy::~CFrameProxy()
  728. {
  729.     ODSafeReleaseObject(fFrame);
  730. }
  731.  
  732. //------------------------------------------------------------------------------
  733. // CFrameProxy::InitFrameProxy (ODDraft)
  734. //------------------------------------------------------------------------------
  735.  
  736. void CFrameProxy::InitFrameProxy(ODID frameID, ODDraft* draft)
  737. {
  738.     ASSERT(draft!=kODNULL, kODErrIllegalNullInput);
  739.     
  740.     fFrame = kODNULL;
  741.     fID = frameID;
  742.     fDraft = draft;
  743. }
  744.     
  745. //------------------------------------------------------------------------------
  746. // CFrameProxy::InitFrameProxy (ODFrame)
  747. //------------------------------------------------------------------------------
  748.  
  749. void CFrameProxy::InitFrameProxy(Environment* ev, ODFrame* frame)
  750. {
  751.     ASSERT(frame!=kODNULL, kODErrIllegalNullFrameInput);
  752.     
  753.     this->SetFrame(ev,frame);
  754. }
  755.  
  756. //------------------------------------------------------------------------------
  757. // CFrameProxy::SetFrame
  758. //
  759. // The code will not affect the proxy fields unless it can
  760. // successfully acquire the incoming frame, its id, and
  761. // the draft the frame lives in. If something goes wrong,
  762. // the proxy remains unchanged.
  763. //------------------------------------------------------------------------------
  764.  
  765. void CFrameProxy::SetFrame(Environment* ev, ODFrame* frame)
  766. {
  767.     ASSERT_NOT_NULL(frame);
  768.     
  769.     // Perform all the operations that can fail first.
  770.     TempODPart    tPart    = frame->AcquirePart(ev);
  771.     ODDraft*    draft    = ODGetDraft(ev, tPart);
  772.     ODID        id        = frame->GetID(ev);
  773.     
  774.     // Release the previously referenced frame and acquire the new one.
  775.     ODTransferReference(ev, fFrame, frame);
  776.  
  777.     // If all went well, set the proxy fields.
  778.     fFrame = frame;
  779.     fID = id;
  780.     fDraft = draft;
  781. }
  782.  
  783. //------------------------------------------------------------------------------
  784. // CFrameProxy::GetFrame
  785. //------------------------------------------------------------------------------
  786.  
  787. ODFrame* CFrameProxy::GetFrame(Environment* ev)
  788. {
  789.     if ( fFrame == kODNULL )
  790.     {
  791.         TRY
  792.             TempODFrame frame = fDraft->AcquireFrame(ev, fID);
  793.             this->SetFrame(ev,frame);
  794.         CATCH_ALL
  795.             fFrame = kODNULL;
  796.             fID = kODNULLID;
  797.         ENDTRY
  798.     }
  799.     return fFrame;
  800. }
  801.  
  802. //------------------------------------------------------------------------------
  803. // CFrameProxy::FrameIsLoaded
  804. //------------------------------------------------------------------------------
  805.  
  806. ODBoolean CFrameProxy::FrameIsLoaded(Environment* ev)
  807. {
  808.     ODBoolean loaded = (fFrame != kODNULL ||
  809.                         fDraft->IsValidID(ev, fID));
  810.     return loaded;
  811. }
  812.  
  813. //------------------------------------------------------------------------------
  814. // CFrameProxy::Purge
  815. //------------------------------------------------------------------------------
  816.  
  817. void CFrameProxy::Purge(Environment* ev)
  818. {
  819.     if ( fFrame != kODNULL )
  820.     {
  821.         fID = fFrame->GetID(ev);
  822.         ODReleaseObject(ev, fFrame);
  823.     }
  824. }
  825.  
  826. //==============================================================================
  827. // CFrameInfo
  828. //==============================================================================
  829. #pragma mark • CFrameInfo •
  830.  
  831. //------------------------------------------------------------------------------
  832. // CFrameInfo::CFrameInfo
  833. //------------------------------------------------------------------------------
  834.  
  835. CFrameInfo::CFrameInfo(ODSession* session)
  836. {
  837.     fSession = session;
  838.     fFrameActive = kODFalse;
  839.     fFrameReactivate  = kODFalse;
  840.     fShouldDisposeWindow = kODFalse;
  841.     fActiveFacet = kODNULL;
  842.     fSourceFrame = kODNULL;
  843.     fDependentFrame = kODNULL;
  844.     fPartWindowID = kODNULLID; 
  845. }
  846.  
  847. //------------------------------------------------------------------------------
  848. // CFrameInfo::~CFrameInfo
  849. //------------------------------------------------------------------------------
  850.  
  851. CFrameInfo::~CFrameInfo()
  852. {
  853.     // Deleting the proxies will release the encapsulated frames.
  854.     ODDeleteObject(fDependentFrame);
  855.     ODDeleteObject(fSourceFrame);
  856. }
  857.  
  858. //------------------------------------------------------------------------------
  859. // CFrameInfo::Externalize
  860. //------------------------------------------------------------------------------
  861.  
  862. void CFrameInfo::Externalize(Environment* ev, ODStorageUnitView* storageUnitView)
  863. {
  864.     // This method assumes that OpenDoc has passed us a storageUnitView
  865.     // that is focused to a property, but no particular value.
  866.     
  867.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  868.  
  869.     this->CleanseFrameInfoProperty(ev, storageUnit);
  870.     this->ExternalizeFrameInfo(ev, storageUnit, kODNULLKey, kODNULL);
  871. }
  872.  
  873. //------------------------------------------------------------------------------
  874. // CFrameInfo::CleanseFrameInfoProperty
  875. //------------------------------------------------------------------------------
  876.  
  877. void CFrameInfo::CleanseFrameInfoProperty( Environment*        ev, 
  878.                                            ODStorageUnit*    storageUnit )
  879. {
  880.     ODULong numValues;
  881.     ODULong index;
  882.         
  883.     numValues = storageUnit->CountValues(ev);
  884.     
  885.     for (index = numValues; index >= 1; index--)
  886.     {
  887.         // Index, from 1 to n, through the values.
  888.         storageUnit->Focus(ev, kODNULL, kODPosSame, kODNULL, index, 
  889.                            kODPosUndefined);
  890.                                 
  891.         // Get the ISO type name for the value. The temp object
  892.         // will automatically delete the returned value when this
  893.         // scope is exited.
  894.         TempODValueType value = storageUnit->GetType(ev);
  895.         
  896.         // If the value type is not one we support, remove it.
  897.         if ( !ODISOStrEqual(value, kCappuccinoInfo) )
  898.             storageUnit->Remove(ev);
  899.     }
  900. }
  901.  
  902. //------------------------------------------------------------------------------
  903. // CFrameInfo::ExternalizeFrameInfo
  904. //------------------------------------------------------------------------------
  905.  
  906. void CFrameInfo::ExternalizeFrameInfo( Environment*        ev, 
  907.                                        ODStorageUnit*    storageUnit,
  908.                                        ODDraftKey        key, 
  909.                                        ODFrame*            scopeFrame )
  910. {
  911.     // This method behaves much the same way as the Cappuccino::ExternalizeStateInfo
  912.     // method.
  913.     
  914.     if ( ODSUExistsThenFocus(ev, storageUnit, kODNULL, kCappuccinoInfo) )
  915.     {
  916.         // Persistent object references are stored in a side table, rather than
  917.         // in the property/value stream. Thus, deleting the contents of a value
  918.         // will not "delete" the references previously written to that value. To
  919.         // completely "delete" all references written to the value, we must
  920.         // remove the value and add it back.
  921.         storageUnit->Remove(ev);
  922.     }
  923.  
  924.     // Add a value to write the data into.
  925.     storageUnit->AddValue(ev, kCappuccinoInfo);
  926.     
  927.     // Write a weak reference to our source frame.
  928.     if ( fSourceFrame )
  929.     {
  930.         ODID frameID = fSourceFrame->GetID();
  931.  
  932.         // If a draft key exists, then we are being cloned to another draft.
  933.         // We must "weak" clone our display frame and reference the cloned
  934.         // frame. The part re-uses the frameID variable so there aren't two
  935.         // different GetWeakStorageUnitRef calls.
  936.         if ( key )
  937.         {
  938.             ODID     scopeFrameID = (scopeFrame ? scopeFrame->GetID(ev) : kODNULLID);
  939.             ODDraft* fromDraft = fSourceFrame->GetDraft();
  940.             frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  941.         }
  942.         
  943.         // Write out weak references to each of the part's display frames.
  944.         ODSetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL, frameID);
  945.     }
  946.     else
  947.     {
  948.         ODStorageUnitRef emptyRef = {0,0,0,0};
  949.         StorageUnitSetValue(storageUnit, ev, kODStorageUnitRefSize, &emptyRef);
  950.     }
  951.     
  952.     // Write a weak reference to our dependent frame.
  953.     if ( fDependentFrame )
  954.     {
  955.         ODID frameID = fDependentFrame->GetID();
  956.         // If a draft key exists, then we are being cloned to another draft.
  957.         // We must "weak" clone our display frame and reference the cloned
  958.         // frame. The part re-uses the frameID variable so there aren't two
  959.         // different GetWeakStorageUnitRef calls.
  960.         if ( key )
  961.         {
  962.             ODID     scopeFrameID = (scopeFrame ? scopeFrame->GetID(ev) : kODNULLID);
  963.             ODDraft* fromDraft = fDependentFrame->GetDraft();
  964.             frameID = fromDraft->WeakClone(ev, key, frameID, kODNULLID, scopeFrameID);
  965.         }
  966.         
  967.         // Write out weak references to each of the part's display frames.
  968.         ODSetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL, frameID);
  969.     }
  970.     else
  971.     {
  972.         ODStorageUnitRef emptyRef = {0,0,0,0};
  973.         StorageUnitSetValue(storageUnit, ev, kODStorageUnitRefSize, &emptyRef);
  974.     }
  975. }
  976.  
  977. //------------------------------------------------------------------------------
  978. // CFrameInfo::CloneInto
  979. //------------------------------------------------------------------------------
  980.  
  981. void CFrameInfo::CloneInto(Environment *ev, ODDraftKey key,
  982.                             ODStorageUnitView* storageUnitView, ODFrame* scopeFrame)
  983. {
  984.     // This method assumes that OpenDoc has passed us a storageUnitView
  985.     // that is focused to a property, but no particular value.
  986.     
  987.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  988.  
  989.     if ( !storageUnit->Exists(ev, kODNULL, kCappuccinoInfo, 0) )
  990.     {
  991.         this->ExternalizeFrameInfo(ev, storageUnit, key, scopeFrame);
  992.     }
  993. }
  994.  
  995. //------------------------------------------------------------------------------
  996. // CFrameInfo::InitFromStorage
  997. //------------------------------------------------------------------------------
  998.  
  999. void CFrameInfo::InitFromStorage(Environment* ev, ODStorageUnitView* storageUnitView)
  1000. {
  1001.     // This method assumes that OpenDoc has passed us a storageUnitView
  1002.     // that is focused to a property, but no particular value.
  1003.     
  1004.     ODStorageUnit* storageUnit = storageUnitView->GetStorageUnit(ev);
  1005.  
  1006.     if ( ODSUExistsThenFocus(ev, storageUnit, kODNULL, kCappuccinoInfo) )
  1007.     {
  1008.         TRY
  1009.             ODID frameID = ODGetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL);
  1010.             if ( frameID != kODNULLID )
  1011.             {
  1012.                 // Create a proxy class to support the lazy internalization.
  1013.                 CFrameProxy* proxy = new CFrameProxy;
  1014.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev, storageUnit));
  1015.  
  1016.                 // Store the proxy source frame.
  1017.                 fSourceFrame = proxy;
  1018.             }
  1019.             
  1020.         CATCH_ALL
  1021.             ODDeleteObject(fSourceFrame);
  1022.             fSourceFrame = kODNULL;
  1023.         ENDTRY
  1024.  
  1025.         TRY
  1026.             ODID frameID = ODGetWeakSURefProp(ev, storageUnit, kODNULL, kODNULL);
  1027.             if ( frameID != kODNULLID )
  1028.             {
  1029.                 // Create a proxy class to support the lazy internalization.
  1030.                 CFrameProxy* proxy = new CFrameProxy;
  1031.                 proxy->InitFrameProxy(frameID, ODGetDraft(ev, storageUnit));
  1032.  
  1033.                 // Store the proxy dependent frame.
  1034.                 fDependentFrame = proxy;
  1035.             }
  1036.             
  1037.         CATCH_ALL
  1038.             ODDeleteObject(fDependentFrame);
  1039.             fDependentFrame = kODNULL;
  1040.         ENDTRY
  1041.     }
  1042. }
  1043.  
  1044. //------------------------------------------------------------------------------
  1045. // CFrameInfo::SetSourceFrame
  1046. //------------------------------------------------------------------------------
  1047.  
  1048. void CFrameInfo::SetSourceFrame(Environment* ev, ODFrame* frame)
  1049. {
  1050.     if ( frame != kODNULL )
  1051.     {
  1052.         // Create a proxy class to support the lazy internalization.
  1053.         CFrameProxy* proxy = new CFrameProxy;
  1054.         proxy->InitFrameProxy(ev,frame);
  1055.         
  1056.         // Store the proxy source frame after clearing the old one.
  1057.         ODDeleteObject(fSourceFrame);
  1058.         fSourceFrame = proxy;
  1059.     }
  1060. }
  1061.  
  1062. //------------------------------------------------------------------------------
  1063. // CFrameInfo::ReleaseSourceFrame
  1064. //------------------------------------------------------------------------------
  1065.  
  1066. void CFrameInfo::ReleaseSourceFrame(Environment* ev)
  1067. {
  1068.     ODDeleteObject(fSourceFrame);
  1069. }
  1070.  
  1071. //------------------------------------------------------------------------------
  1072. // CFrameInfo::SetDependentFrame
  1073. //------------------------------------------------------------------------------
  1074.  
  1075. void CFrameInfo::SetDependentFrame(Environment* ev, ODFrame* frame)
  1076. {
  1077.     if ( frame != kODNULL )
  1078.     {
  1079.         // Create a proxy class to support the lazy internalization.
  1080.         CFrameProxy* proxy = new CFrameProxy;
  1081.         proxy->InitFrameProxy(ev,frame);
  1082.         
  1083.         // Store the proxy dependent frame after clearing the old one.
  1084.         ODDeleteObject(fDependentFrame);
  1085.         fDependentFrame = proxy;
  1086.     }
  1087. }
  1088.  
  1089. //------------------------------------------------------------------------------
  1090. // CFrameInfo::ReleaseDependentFrame
  1091. //------------------------------------------------------------------------------
  1092.  
  1093. void CFrameInfo::ReleaseDependentFrame(Environment* ev)
  1094. {
  1095.     ODDeleteObject(fDependentFrame);
  1096. }
  1097.  
  1098. //------------------------------------------------------------------------------
  1099. // CFrameInfo::AcquirePartWindow
  1100. //------------------------------------------------------------------------------
  1101.  
  1102. ODWindow* CFrameInfo::AcquirePartWindow(Environment* ev)
  1103. {
  1104.     ODWindow* window = kODNULL;
  1105.     
  1106.     if ( fPartWindowID )
  1107.     {
  1108.         window = fSession->GetWindowState(ev)->AcquireWindow(ev,fPartWindowID);
  1109.         if ( !window ) 
  1110.             fPartWindowID = kODNULLID;
  1111.     }
  1112.     
  1113.     return window;
  1114. }
  1115.  
  1116. //------------------------------------------------------------------------------
  1117. // CFrameInfo::SetPartWindow
  1118. //------------------------------------------------------------------------------
  1119.  
  1120. void CFrameInfo::SetPartWindow(Environment* ev, ODWindow* window)
  1121. {
  1122.     fPartWindowID = window ? window->GetID(ev) : kODNULLID;
  1123. }
  1124.  
  1125. //------------------------------------------------------------------------------
  1126. // CFrameInfo::GetFrameInfo (ODFrame)                                [static]
  1127. //------------------------------------------------------------------------------
  1128.  
  1129. CFrameInfo* CFrameInfo::GetFrameInfo(Environment* ev, ODFrame* frame)
  1130. {
  1131.     ASSERT_NOT_NULL(frame);
  1132.     return (CFrameInfo*) frame->GetPartInfo(ev);
  1133. }
  1134.  
  1135. //------------------------------------------------------------------------------
  1136. // CFrameInfo::GetFrameInfo (ODFacet)                                [static]
  1137. //------------------------------------------------------------------------------
  1138.  
  1139. CFrameInfo* CFrameInfo::GetFrameInfo(Environment* ev, ODFacet* facet)
  1140. {
  1141.     ASSERT_NOT_NULL(facet);
  1142.     return CFrameInfo::GetFrameInfo(ev, facet->GetFrame(ev));
  1143. }
  1144.  
  1145.